﻿using NCS.IConnect.Core.Utilities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using System.Web.Http.Metadata;

namespace NCS.IConnect.Core.WebApi.Description
{
    /// <summary>
    /// The URI based parameter specific descriptor.
    /// </summary>
    public class UriParameterDescriptor
    {
        /// <summary>
        /// Gets the <see cref="ApiActionDescriptor"/>.
        /// </summary>
        /// <value>The <see cref="ApiActionDescriptor"/>.</value>
        [JsonIgnore]
        public ApiActionDescriptor ActionDescriptor { get; private set; }

        /// <summary>
        /// Gets or sets <see cref="HttpParameterDescriptor"/>.
        /// </summary>
        /// <value>The <see cref="HttpParameterDescriptor"/>.</value>
        [JsonIgnore]
        public HttpParameterDescriptor HttpParameterDescriptor { get; protected set; }

        /// <summary>
        /// Gets the model metadata.
        /// </summary>
        /// <value>The model metadata.</value>
        [JsonIgnore]
        public ModelMetadata ModelMetadata { get; private set; }

        /// <summary>
        /// Gets the documentation provider.
        /// </summary>
        /// <value>The documentation provider.</value>
        [JsonIgnore]
        public IDocumentationProvider DocumentationProvider { get; private set; }

        /// <summary>
        /// Gets the name of the parameter.
        /// </summary>
        /// <value>The name of the parameter.</value>
        public string ParameterName { get; internal set; }

        /// <summary>
        /// Gets the type of the parameter.
        /// </summary>
        /// <value>The type of the parameter.</value>
        public Type ParameterType { get; internal set; }

        /// <summary>
        /// Gets the description.
        /// </summary>
        /// <value>The description.</value>
        public string Description { get; internal set; }

        /// <summary>
        /// Gets a value indicating whether this instance is optional.
        /// </summary>
        /// <value><c>true</c> if this instance is optional; otherwise, <c>false</c>.</value>
        public bool IsOptional { get; internal set; }

        /// <summary>
        /// Gets the default value.
        /// </summary>
        /// <value>The default value.</value>
        public object DefaultValue { get; internal set; }

        /// <summary>
        /// Gets or sets the remark.
        /// </summary>
        /// <value>The remark.</value>
        public string Remark { get; set; }

        /// <summary>
        /// Get the descriptive name of parameter type.
        /// </summary>
        /// <returns>The descriptive name of parameter type.</returns>
        public string GetParameterTypeName()
        {
            if (this.ParameterType.IsGenericType)
            {
                string genericParameters = string.Join(",", this.ParameterType.GetGenericArguments().Select(it => it.Name).ToArray());
                string genericTypeDefinition = this.ParameterType.GetGenericTypeDefinition().Name;
                return string.Format("{0}<{1}>", genericTypeDefinition.Substring(0,genericTypeDefinition.IndexOf('`')),genericParameters);
            }
            return this.ParameterType.Name;
        }

        /// <summary>
        /// Get default value represented in the form of string.
        /// </summary>
        /// <returns>The default value represented in the form of string.</returns>
        public string GetDefaultValueAsString()
        {
            if (null == this.DefaultValue)
            {
                return "<null>";
            }
            return this.DefaultValue.ToString();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UriParameterDescriptor"/> class.
        /// </summary>
        /// <param name="actionDescriptor">The <see cref="ApiActionDescriptor"/>.</param>
        /// <param name="httpParameterDescriptor">The <see cref="HttpParameterDescriptor"/>.</param>
        public UriParameterDescriptor(ApiActionDescriptor actionDescriptor, HttpParameterDescriptor httpParameterDescriptor = null)
        {
            Guard.ArgumentNotNull(actionDescriptor, "actionDescriptor");

            this.ActionDescriptor = actionDescriptor;
            this.DocumentationProvider = actionDescriptor.DocumentationProvider;
            this.HttpParameterDescriptor = httpParameterDescriptor;

            if (null != this.HttpParameterDescriptor)
            {
                this.Description = this.DocumentationProvider.GetDocumentation(httpParameterDescriptor);
                this.ParameterName = httpParameterDescriptor.ParameterName;
                this.ParameterType = httpParameterDescriptor.ParameterType;
                this.IsOptional = httpParameterDescriptor.IsOptional;
                this.DefaultValue = httpParameterDescriptor.DefaultValue;
            }
        }
    }
}